package cn.iocoder.yudao.module.trade.service.drainage;

import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.module.trade.controller.admin.orderpostback.vo.OrderPostBackSaveReqVO;
import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderDO;
import cn.iocoder.yudao.module.trade.dal.dataobject.orderpostback.OrderPostBackDO;
import cn.iocoder.yudao.module.trade.dal.dataobject.orderpostconfig.OrderPostConfigDO;
import cn.iocoder.yudao.module.trade.enums.orderpostback.OrderPostBackPayTypeEnum;
import cn.iocoder.yudao.module.trade.enums.orderpostback.TradeOrderPostBackStatusEnum;
import cn.iocoder.yudao.module.trade.service.orderpostback.OrderPostBackService;
import com.alibaba.fastjson.JSONObject;
import lombok.Getter;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDateTime;
import java.util.Map;
import java.util.stream.Stream;

/**
 * 抖音落地页
 */
@Slf4j
@Service
public class DouyinDrainageServiceImpl implements DrainageService {

    @Getter
    @Setter
    public Integer drainageType = 3; //抖音类型
    @Value("${drainage.type.douyin.server:https://analytics.oceanengine.com/api/v2/conversion}")
    private String serverUrl;

    @Resource
    private OrderPostBackService orderPostBackService;
    @Resource
    protected RestTemplate restTemplate;

    @Override
    public boolean processOrder(TradeOrderDO orderDO, Map<String, String> param, OrderPostConfigDO configDo, boolean send) {
        OrderPostBackSaveReqVO saveReqVO = createOrderPostBack(orderDO, param.get("clickid"), drainageType,
                orderDO.getPayPrice(), 1, configDo, send ? TradeOrderPostBackStatusEnum.UN_SEND : TradeOrderPostBackStatusEnum.OFF_SHELF);
        if (send) {
            sendOrder(saveReqVO);
        }
        orderPostBackService.createOrderPostBack(saveReqVO);
        return true;
    }

    @Override
    public boolean processOrder(OrderPostBackDO orderPostBackDO) {
        OrderPostBackSaveReqVO saveReqVO = BeanUtils.toBean(orderPostBackDO, OrderPostBackSaveReqVO.class);
        sendOrder(saveReqVO, true);
        orderPostBackService.createOrderPostBack(saveReqVO);
        return true;
    }

    private boolean sendOrder(OrderPostBackSaveReqVO saveReqVO, boolean retry) {
        int type;
        if (OrderPostBackPayTypeEnum.PAY.getType().equals(saveReqVO.getOrderType())) {
            type = 5;
        } else if (OrderPostBackPayTypeEnum.REFUND.getType().equals(saveReqVO.getOrderType())) {
            type = 8;
        } else {
            log.error("未找到对应回传类型: {}", saveReqVO.getOrderType());
            return false;
        }
        try {
            HttpHeaders headers = new HttpHeaders();
            headers.setContentType(MediaType.APPLICATION_JSON);
            boolean success = Stream.of("active_pay", "form", "customer_effective", "work_wechat_added").map(item -> {
                ResponseEntity<String> response = restTemplate.postForEntity(
                        serverUrl, createBody(headers, item, saveReqVO.getThirdId(), System.currentTimeMillis()),
                        String.class
                );
                log.info("字节回传响应: {}", response);
                return response.getBody();
            }).filter(StringUtils::isNoneEmpty).anyMatch(this::successResponse);
            saveReqVO.setStatus(success ?
                    TradeOrderPostBackStatusEnum.FINISH.getStatus() :
                    retry ? TradeOrderPostBackStatusEnum.FAILED.getStatus() : TradeOrderPostBackStatusEnum.RETRY_FAILED.getStatus());
            return success;
        } catch (Exception e) {
            log.error("回传变现猫数据失败：{}", e.getMessage());
            saveReqVO.setStatus(retry ? TradeOrderPostBackStatusEnum.FAILED.getStatus() : TradeOrderPostBackStatusEnum.RETRY_FAILED.getStatus());
            return false;
        } finally {
            saveReqVO.setPostTime(LocalDateTime.now());
        }
    }

    private boolean successResponse(String res) {
        if (StringUtils.isNoneEmpty(res)) {
            JSONObject jsonObject = JSONObject.parseObject(res);
            return jsonObject.containsKey("code") && jsonObject.getIntValue("code") == 0;
        }
        return false;
    }

    /**
     * 创建请求体
     * @param eventType
     * @param clickId
     * @param timestamp
     * @return
     */
    private HttpEntity<String> createBody(HttpHeaders headers, String eventType, String clickId, long timestamp) {
        String param = String.format("{" +
                "    \"event_type\": %s," +
                "    \"context\": {" +
                "        \"ad\": {" +
                "            \"callback\": %s" +
                "        }" +
                "    }," +
                "    \"timestamp\": %d" +
                "}", eventType, clickId, timestamp);
        return new HttpEntity<>(param, headers);
    }

    @Override
    public boolean unPayOrderPost(TradeOrderDO tradeOrderDO, Map<String, String> param, OrderPostConfigDO configDO) {
        return false;
    }

    private boolean sendOrder(OrderPostBackSaveReqVO saveReqVO) {
        return sendOrder(saveReqVO, false);
    }
}
